<template>
  <q-select
    :class="'select-' + field.name"
    filled
    use-input
    :clearable="clearable"
    v-model="serialization"
    :emit-value="emitvalue"
    :map-options="mapoptions"
    :multiple="!!field.multiple"
    :options="_options"
    :label="field.label"
    lazy-rules
    :rules="field.rules ? field.rules : null"
    @filter="filterFn"
    :readonly="readonly"
    :dense="dense"
    @new-value="createValue"
    ref="select"
    bottom-slots
    :autofocus="field.autofocus"
    @clear="onClear"
    :loading="loading"
    @virtual-scroll="onScroll"
    v-bind="$attrs"
  >
    <template v-slot:no-option>
      <q-item>
        <q-item-section class="text-grey">
          No results
        </q-item-section>
      </q-item>
    </template>
    <template v-slot:hint v-if="field.hint || field.compare">
      <div class="text-bold text-white bg-yellow-10" style="padding: 1px;" v-if="canShowCompare">
        {{field.compare.label ? field.compare.label + '：' : ''}}{{field.compare.map ? showCompareValue(field.compare.map.value) : showCompareValue(field.compare.value)}}
      </div>
      <div v-if="field.hint">{{field.hint}}</div>
    </template>
    <template v-slot:after v-if="field.btn && field.btn.fn">
      <q-btn
        :id="'select-' + field.name + '-btn'"
        :disable="!!field.btn.disable"
        dense
        :flat="!!field.btn.flat"
        :label="field.btn.label || ''"
        :icon="field.btn.icon || undefined"
        :color="field.btn.color || undefined"
        @click="field.btn.fn(field)"
      >
        <q-tooltip v-if="field.btn.hint">{{ field.btn.hint }}</q-tooltip>
      </q-btn>
    </template>
  </q-select>
</template>

<script>
import { defineComponent } from 'vue';
import pinyin from 'src/lib/vue-py';
import { useStore } from 'stores/store';

export default defineComponent({
  name: 'filterSelect',
  props: {
    field: {
      type: Object,
      default: () => []
    },
    modelValue: {
      type: [String, Object],
      default: ''
    }
  },
  emits: ['update:modelValue'],
  data () {
    const $store = useStore();
    if (!this.field.options) this.field.options = [];
    if (this.field.dict && $store.dictionary[this.field.dict] && this.field.options.length == 0) {
      this.field.options = Object.freeze(JSON.parse(JSON.stringify($store.dictionary[this.field.dict])));
    }

    return {
      options: this.field.options,

      pageSize: 30,
      nextPage: 2,
      lastPage: 0,
      loading: false,
      $store
    }
  },
  methods: {
    filterFn (val, update, abort) {
      const $store = useStore();
      if (typeof this.field.filterFn === 'function') {
        this.field.filterFn(val, abort, opts => {
          update(() => {
            this.options = opts;
          });
        });
      } else {
        if (!this.field.options) this.field.options = [];
        if (this.field.dict && $store.dictionary[this.field.dict] && this.field.options.length == 0) {
          this.field.options = JSON.parse(JSON.stringify($store.dictionary[this.field.dict]));
        }
        update(() => {
          this.options = this.field.options.filter(v => {
            const py = v._py || pinyin.chineseToPinYin(v.label || '', true).toLowerCase() || '';
            return v.label && (v.label.indexOf(val) > -1 || py.indexOf(val.toLowerCase()) > -1)
          })
        })
      }
    },
    sendOption (val) {
      // 把选中option发送出去
      if (this.emitvalue) {
        if (val === '' || val === null || val === undefined) { // 空值
          this.field.selected = null;
        } else {
          const self = this;
          const valArr = String(val).split(',');
          const optArr = [];
          valArr.forEach(item => {
            optArr.push(self.options.filter(v => v.value == item)[0]);
          });
          this.field.selected = optArr;
        }
      }
    },
    createValue (val, done) {
      if (this.field.newValue) { // 可以添加自定义内容
        const trimVal = String(val).trim();
        if (trimVal.length > 0) {
          const selected = this.field.options.filter(v => v.label == trimVal);
          if (selected.length < 1) { // 新数据添加新列表
            // this.field.options.push({ value: trimVal, label: trimVal });
            // this.options = this.field.options;
            done(trimVal, 'toggle');
          } else { // 老数据触发
            done(selected[0].value, 'toggle');
          }
        }
      }
    },
    onClear (value) {
      this.field.value = '';
    },
    onScroll ({ to, ref }) {
      const lastIndex = this._options.length - 1;

      if (this.loading !== true && this.nextPage <= this.lastPage && to === lastIndex) {
        this.loading = true;

        setTimeout(() => {
          this.nextPage++;
          this.$nextTick(() => {
            ref.refresh();
            this.loading = false;
          })
        }, 500);
      }
    },
    showCompareValue (val) {
      if (val && typeof val === 'object') {
        return val.label;
      } else {
        return val;
      }
    }
  },
  computed: {
    serialization: {
      get () {
        let val = this.field.value;
        if (val === '' || val === undefined) val = null;

        this.sendOption(val);
        if (this.field.multiple && this.emitvalue) {
          return val && String(this.field.value).split(',').map(v => !isNaN(v) ? parseInt(v) : v); // 多选时为数组
        } else {
          return this.field.value;
        }
      },
      set (val) {
        if (this.field.multiple && this.emitvalue) {
          val = Object.prototype.toString.call(val) === '[object Array]' && val.length === 0 ? null : val; // 返回为空数组时置为null
          this.field.value = val && val.join(',');
        } else {
          this.field.value = val;
        }
        this.$emit('update:modelValue', this.field.value);
      }
    },
    emitvalue () {
      if (this.field.emitvalue === false) {
        return false;
      } else {
        return true;
      }
    },
    mapoptions () {
      if (this.field.mapoptions === false) {
        return false;
      } else {
        return true;
      }
    },
    readonly () {
      return !!this.field.readonly;
    },
    dense () {
      return !!this.field.dense;
    },
    clearable () {
      return this.field.clearable === undefined || this.field.clearable === null ? true : !!this.field.clearable;
    },
    canShowCompare () {
      /*
        compare的值
        compare: {
          label, // 标题
          value, // 对比的值
          always // true-有数据就显示 false-值不同，再显示
        } */
      let compareValue, fieldValue = '';
      if (this.field.compare) {
        compareValue = typeof this.field.compare.value === 'object' && this.field.compare.value != null ? this.field.compare.value.value : this.field.compare.value;
        fieldValue = typeof this.field.value === 'object' && this.field.value !== null ? this.field.value.value : this.field.value;
      }

      return this.field.compare && this.field.compare.value !== null && (this.field.compare.always || compareValue != fieldValue);
    },
    _options () {
      let curOpt = null;

      if (typeof this.field.value == 'object' && this.field.value !== null && this.field.value !== undefined) {
        curOpt = this.field.value;
      } else {
        const opt = this.options.filter(v => v.value == this.field.value);
        if (opt.length > 0) {
          curOpt = opt[0];
        }
      }

      const selectOptions = this.options.slice(0, this.pageSize * (this.nextPage - 1));

      if (curOpt && selectOptions.filter(v => v.value == curOpt.value).length === 0) {
        selectOptions.push(curOpt);
      }
      return selectOptions;

      // return Object.freeze(this.options.slice(0, this.pageSize * (this.nextPage - 1)));
    }
  },
  watch: {
    '$store.dictionary' (val) { // 字典有数据后，加载到options
      if (this.field.dict && val[this.field.dict] && this.options.length < 1) {
        this.field.options = JSON.parse(JSON.stringify(this.$store.dictionary[this.field.dict]));
        this.options = this.field.options;
      }
    },
    options (val) {
      this.lastPage = Math.ceil(this.options.length / this.pageSize);
    }
  }
});
</script>
